#include "opto_devices_manager.hpp"

// Opto C API
#include "OptoDevicesManager.h"

namespace Opto
{
	//============================================================================
	// Opto::DevicesManager (10/11/2020)
	// Opto DevicesManager class, use to discover drivers & devices
	//============================================================================
	namespace DevicesManager
	{
		void DevicesManager::discoverDrivers(const std::string& driversPath)
		{
			int count = 0;
			int error = OptoDevicesManager_DiscoverDrivers(driversPath.c_str(), &count);
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::discoverDrivers");
		}

		std::vector<std::string> DevicesManager::discoveredDrivers()
		{
			int count;
			std::vector<std::string> drivers;
			int error = OptoDevicesManager_EnumerateDrivers(OptoDeviceTypeAll, nullptr, &count);
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::discoveredDrivers");		
			if(count > 0)
			{
				OptoDriverInfos* lpDrvInfos = new OptoDriverInfos[count];
				OptoDevicesManager_EnumerateDrivers(OptoDeviceTypeAll, lpDrvInfos, &count);
				if(lpDrvInfos)
				{
					for(int i=0; i<count; i++)
						drivers.push_back(std::string(lpDrvInfos[i].name));
					delete [] lpDrvInfos;
				}
			}
			return drivers;
		}


		void DevicesManager::loadAllDrivers()
		{
			int error = OptoDevicesManager_LoadAllDrivers();
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::loadAllDrivers");		
		}

		void DevicesManager::unloadAllDrivers()
		{
			int error = OptoDevicesManager_UnLoadAllDrivers();
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::unloadAllDrivers");	
		}

		void DevicesManager::loadDriver(const std::string& driver)
		{
			int error = OptoDevicesManager_LoadDriver(driver.c_str());
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::loadDriver");	
		}

		void DevicesManager::unloadDriver(const std::string& driver)
		{
			int error = OptoDevicesManager_UnLoadDriver(driver.c_str());
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::unloadDriver");	
		}

		bool DevicesManager::isDriverLoaded(const std::string& driver) 
		{
			int error = OptoDevicesManager_IsDriverLoaded(driver.c_str());
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::isDriverLoaded");	
			return OPTO_SUCCEEDED(error);
		}

		void DevicesManager::discoverDevices()
		{
			int count = 0;
			int error = OptoDevicesManager_DiscoverDevices(&count);
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::discoverDevices");
		}

		std::vector<std::string> discoveredDevices()
		{
			int count;
			std::vector<std::string> devices;
			int error = OptoDevicesManager_EnumerateDevices(OptoDeviceTypeAll, nullptr, &count);
			if(OPTO_FAILED(error))
				throw Exception(error, "Opto::DevicesManager::discoveredDevices");		
			if(count > 0)
			{
				OptoDeviceInfos* lpDevInfos = new OptoDeviceInfos[count];
				OptoDevicesManager_EnumerateDevices(OptoDeviceTypeAll, lpDevInfos, &count);
				if(lpDevInfos)
				{
					for(int i=0; i<count; i++)
						devices.push_back(std::string(lpDevInfos[i].deviceId));
					delete [] lpDevInfos;
				}
			}
			return devices;
		}

	}; // Opto::DevicesManager namespace

}; // Opto namespace